home *** CD-ROM | disk | FTP | other *** search
/ Aminet 15 / Aminet 15 - Nov 1996.iso / Aminet / dev / misc / FD2Pragma.lha / Source / FD2Pragma.c next >
Encoding:
C/C++ Source or Header  |  1996-09-16  |  35.6 KB  |  1,480 lines

  1. #define NAME     "FD2Pragma"
  2. #define VERSION  "2"
  3. #define REVISION "11"
  4. #define ENDCODE
  5. //#define DEBUG
  6. //#define DEBUG_OLD
  7.  
  8. /* Programmheader
  9.  
  10.     Name:        FD2Pragma
  11.     Author:        SDI
  12.     Distribution:    PD
  13.     Description:    creates pragmas files, lvo files and stub functions
  14.     Compileropts:    -
  15.     Linkeropts:    -l small
  16.  
  17.  1.2    : added pragmas for the Dice compiler. Available via switch "Dice".
  18.     added switches "Aztec", "SAS" and "Maxon": Maxon and Aztec just
  19.     turn on the default (except that Maxon expects pragma files to be
  20.     called "xxx_pragmas.h" instead of "xxx_lib.h"), SAS is equal to
  21.     Dice, except that SAS supports the pragma tagcall.
  22.  2.0    : Added support for tag functions. See the docs for details.
  23.      Author until this version:
  24.         Jochen Wiedmann
  25.     Am Eisteich 9
  26.     72555 Metzingen (Germany)
  27.     Tel. 07123 / 14881
  28.     E-Mail: wiedmann@mailserv.zdv.uni-tuebingen.de
  29.  2.1   19.08.96 : now made by SDI, added correct __MAXON__ support and
  30.      support for StormC++, added auto recognition of tagcall functions
  31.      changed the CLI interface completely
  32.  2.2   21.08.96 : fixed a lot of errors, added debug code
  33.  2.3   22.08.96 : little changes
  34.  2.4   24.08.96 : added proto-file creation
  35.  2.5   25.08.96 : added syscall and fix for functions ending in ...DMA
  36.  2.6   26.08.96 : fixed some errors, added CLIB parameter (used later for
  37.     CSTUBS)
  38.  2.7   01.09.96 : added correct Storm definition, added CLIB scan
  39.  2.8   02.09.96 : added assembler stub functions, added first ASM-stub code
  40.  2.9   04.09.96 : added Comment-Support
  41.  2.10  05.09.96 : changed CSTUB creation a bit
  42.  2.11  07.09.96 : speeded up output, reduced number of strndup calls
  43. */
  44.  
  45. #include <exec/nodes.h>
  46. #include <exec/lists.h>
  47. #include <exec/libraries.h>
  48. #include <exec/memory.h>
  49. #include <dos/doshunks.h>
  50. #include <clib/alib_protos.h>
  51.  
  52. #include <pragma/exec_lib.h>
  53. #include <pragma/dos_lib.h>
  54. #include <pragma/intuition_lib.h>
  55.  
  56. #define SDI_TO_ANSI
  57. #include "SDI_ASM_STD_protos.h"
  58. #include "SDI_defines.h"
  59. #include "SDI_structures.h"
  60.  
  61. #define TEXT_SAS    "__SASC"    // verified
  62. #define TEXT_SAS_60    "__SASC_60"    // verified
  63. #define TEXT_MAXON    "__MAXON__"    // verified
  64. #define TEXT_STORM    "__STORM__"    // verified
  65. #define TEXT_DICE    "_DCC"        // in 2.0 code
  66. #define TEXT_AZTEC    "AZTEC_C"    // verified
  67. #define TEXT_GNUC    "__GNUC__"    // in 2.0 code
  68.  
  69. #define FLAG_EXTERNC    (1<<0)
  70. #define FLAG_PROTOTYPE    (1<<1) //dice
  71. #define FLAG_SYSCALL    (1<<2)
  72. #define FLAG_DOCOMMENT    (1<<3)
  73.  
  74. #define PARAM "FDFILE/A,SPECIAL/N,TO/K,COMMENT/S,MODE/N,AMICALL/K,LIBCALL/K" \
  75.     ",AMITAGS/K,LIBTAGS/K,CSTUBS/K,EXTERNC/S,USESYSCALL/S,CLIB/K"
  76.  
  77. STRPTR RegNames[16] =
  78. { (STRPTR) "d0", (STRPTR) "d1", (STRPTR) "d2", (STRPTR) "d3",
  79.   (STRPTR) "d4", (STRPTR) "d5", (STRPTR) "d6", (STRPTR) "d7",
  80.   (STRPTR) "a0", (STRPTR) "a1", (STRPTR) "a2", (STRPTR) "a3",
  81.   (STRPTR) "a4", (STRPTR) "a5", (STRPTR) "a6", (STRPTR) "a7"
  82. };
  83.  
  84. struct AmiPragma
  85. {
  86.   struct MinNode    Node;
  87.   UWORD            Bias;
  88.   UWORD            Public;
  89.   STRPTR        FuncName;
  90.   STRPTR        TagName;
  91.   STRPTR        Comment;
  92.   ULONG            NumArgs;
  93.   struct AmiArgs
  94.   {
  95.     STRPTR        ArgName;
  96.     UWORD        ArgReg;
  97.   } Args[14];    /*  a6 and a7 must not be used for function arguments    */
  98. };
  99.  
  100. struct RDArgs    *rda            = 0;
  101. struct SDI_InOut in            = {0,0,0,0,0},
  102.          out            = {0,0,5000,0,0};
  103. STRPTR        clibbuf            = 0;
  104. ULONG        clibsize        = 0;
  105. struct FileInfoBlock *fib        = 0;
  106. struct MinList    AmiPragmaList        = {0,0,0};
  107. struct Remember *remember        = 0;
  108. ULONG        oldfh            = 0;
  109. ULONG        lock            = 0;
  110. STRPTR        BaseName        = 0;
  111. STRPTR        ShortBaseName        = 0;
  112. STRPTR        ShortBaseNameUpper    = 0;
  113. ULONG        DosVersion        = 37; // force OS2.0
  114. STRPTR        DESTFILE        = 0;
  115. ULONG        MODE            = 1;
  116. STRPTR        AMICALL            = 0;
  117. STRPTR        LIBCALL            = 0;
  118. STRPTR        AMITAGS            = 0;
  119. STRPTR        LIBTAGS            = 0;
  120. STRPTR        CSTUBS            = 0;
  121. ULONG        Flags            = 0;
  122. struct IntuitionBase *IntuitionBase    = 0;
  123.  
  124. /* Prototypes for the functions */
  125. STRPTR strndup(STRPTR, ULONG);
  126. void DoError(UBYTE, ULONG);
  127. ULONG Out(ULONG);
  128. ULONG DoOutput(STRPTR, ...);
  129. ULONG DoOutputDirect(APTR, ULONG);
  130. STRPTR SkipBlanks(STRPTR);
  131. STRPTR SkipName(STRPTR);
  132. ULONG MakeTagFunction(struct AmiPragma *);
  133. void MakeLines(STRPTR, ULONG, ULONG);
  134. ULONG ScanFDFile(void);
  135. ULONG WriteHeader(void);
  136. ULONG WriteFooter(void);
  137. ULONG WritePragmaAMICALL(struct AmiPragma *, ULONG);
  138. ULONG WritePragmaLIBCALL(struct AmiPragma *, ULONG);
  139. STRPTR FindClibFunc(STRPTR);    // finds the needed function
  140. ULONG GetClibLength(STRPTR);    // returns length of the type
  141. ULONG OutClibType(STRPTR);
  142. STRPTR GetClibType(STRPTR);    // searches for next type definition
  143. ULONG CreateCSTUBS(struct AmiPragma *, ULONG);
  144. ULONG CallPrag(STRPTR, ULONG, ULONG (*) (struct AmiPragma *, ULONG));
  145. ULONG CreatePragmaFile(void);
  146. ULONG CreateLVOFile(ULONG);
  147. ULONG DoAsmText(STRPTR, struct AmiPragma *);
  148. ULONG DoAsmCode(STRPTR, struct AmiPragma *);
  149. ULONG CreateAsmStubs(ULONG);
  150. ULONG CreateProtoFile(ULONG);
  151. void WriteError(void);
  152. void main(void);
  153. void end(void);
  154.  
  155. STRPTR strndup(STRPTR Str, ULONG Len)
  156. {
  157.   STRPTR res;
  158.   if((res = (STRPTR) AllocRemember(&remember, Len+1, MEMF_ANY|MEMF_CLEAR)))
  159.   {
  160.     CopyMem(Str, res, Len);
  161.     res[Len] = '\0';
  162.   }
  163.   return res;
  164. }
  165.  
  166. enum {
  167. ERR_TAGFUNC_NEEDS_ARGUMENT,
  168. ERR_CANNOT_CONVERT_PRAGMA_TAGCALL,
  169. ERR_TAG_DEF_WITHOUT_PRAGMA,
  170. ERR_BASENAME_DECLARED_TWICE,
  171. ERR_EXPECTED_SLASH_IN_BASENAME,
  172. ERR_EXPECTED_BASENAME,
  173. ERR_EXPECTED_BIAS_VALUE,
  174. ERR_ASSUMING_POSITIVE_BIAS_VALUE,
  175. ERR_MISSING_FUNCTION_NAME,
  176. ERR_EXPECTED_OPEN_BRACKET,
  177. ERR_TO_MUCH_ARGUMENTS,
  178. ERR_EXPECTED_ARGUMENT_NAME,
  179. ERR_EXPECTED_CLOSE_BRACKET,
  180. ERR_EXPECTED_REGISTER_NAME,
  181. ERR_ILLEGAL_REGISTER,
  182. ERR_REGISTER_USED_TWICE,
  183. ERR_AGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER,
  184. ERR_ASSUMING_BIAS_OF_30,
  185. ERR_EXTRA_CHARACTERS,
  186. ERR_MISSING_BASENAME,
  187. ERR_WRITING_FILE,
  188. ERR_NO_FILENAME,
  189. };
  190.  
  191. struct ErrField {
  192.   UBYTE  Type;    // 0 = Error, 1 = Warning
  193.   UBYTE  Skip;
  194.   STRPTR Error;
  195. } Errors[] = {
  196. 1, 1, "Tag function must have arguments.",
  197. 1, 1, "Cannot convert pragma name into tag name.",
  198. 1, 1, "Tag definition without preceding Pragma.",
  199. 1, 0, "Basename declared twice.",
  200. 1, 0, "Expected preceding _ in Basename.",
  201. 1, 1, "Expected Basename.",
  202. 1, 0, "Expected Bias value.",
  203. 1, 0, "Assuming positive bias value.",
  204. 1, 1, "Missing function name.",
  205. 1, 1, "Expected '('.",
  206. 1, 1, "Too much arguments.",
  207. 1, 1, "Expected argument name.",
  208. 1, 1, "Expected ')'.",
  209. 1, 1, "Expected register name.",
  210. 1, 1, "A5 and A6 not allowed as argument register.",
  211. 1, 1, "Register used twice.",
  212. 1, 0, "Number of arguments != number of registers.",
  213. 1, 0, "Assuming bias of 30.",
  214. 1, 1, "Extra characters.",
  215. 0, 0, "Missing Basename.",
  216. 0, 0, "Failed to write destination file.",
  217. 0, 0, "No filename given.\n",
  218. };
  219.  
  220. void DoError(UBYTE errnum, ULONG line)
  221. {
  222.   struct {
  223.     STRPTR type;
  224.     ULONG typenum;
  225.     ULONG linenum;
  226.   } args;
  227.   
  228.   args.type = Errors[errnum].Type ? "Warning" : "Error";
  229.   args.typenum = errnum;
  230.   args.linenum = line;
  231.  
  232.   VPrintf((line ? "%s %ld in line %ld: " : "%s %ld : "), &args);
  233.   VPrintf("%s\n", &Errors[errnum].Error);
  234.   if(line && Errors[errnum].Skip)
  235.   {
  236.     while(*in.pos)
  237.       ++in.pos;
  238.   }
  239. }
  240.  
  241. ULONG Out(ULONG size)
  242. {
  243.   ULONG i = out.pos-out.buf;
  244.  
  245.   if(i && out.size - i <= size)
  246.   {
  247.     if(Write(out.file, out.buf, i) != i)
  248.       return 0;
  249.     out.count += i;
  250.     out.pos = out.buf;
  251.   }
  252.   return out.size;
  253. }
  254.  
  255. #ifdef __MAXON__
  256.   #define __asm
  257. #endif
  258.  
  259. static void __asm putfunc(register __d0 UBYTE data, register __a3 LONG *a)
  260. {
  261.   if(!*a)
  262.     *a = Out(1);
  263.   if((*a)-- > 0)
  264.     *(out.pos++) = data;
  265. }
  266.  
  267. typedef void (*putchtype) ();
  268.  
  269. ULONG DoOutput(STRPTR format, ...)
  270. {
  271.   LONG a = out.buf+out.size-out.pos;
  272.   RawDoFmt(format, (APTR) ((ULONG)&format+sizeof(STRPTR)),
  273.   (putchtype) putfunc, &a);
  274.  
  275.   if(a >= 0)
  276.   {
  277.     --out.pos;
  278.     return 1;
  279.   }
  280.  
  281.   return 0;
  282. }
  283.  
  284. ULONG DoOutputDirect(APTR data, ULONG size)
  285. {
  286.   if(!Out(size))
  287.     return 0;
  288.   CopyMem(data, out.pos, size);
  289.   out.pos += size;
  290.   return 1;
  291. }
  292.  
  293. STRPTR SkipBlanks(STRPTR OldPtr)
  294. {
  295.   while(*OldPtr == ' ' || *OldPtr == '\t')
  296.     ++OldPtr;
  297.   return OldPtr;
  298. }
  299.  
  300. /*
  301.     This function is used to skip over variable names.
  302.  
  303.     Inputs: OldPtr  - pointer to the beginning of a string.
  304.  
  305.     Result: Pointer to the first character of the string, that is not one
  306.         of a-z, A-Z, 0-9 or the underscore.
  307. */
  308.  
  309. STRPTR SkipName(STRPTR OldPtr)
  310. {
  311.   while(isalnum(*OldPtr) || *OldPtr == '_')
  312.     ++OldPtr;
  313.   return OldPtr;
  314. }
  315.  
  316. ULONG MakeTagFunction(struct AmiPragma *ap)
  317. {
  318. #ifdef DEBUG_OLD
  319.   VPrintf("MakeTagFunction:\n", 0);
  320. #endif
  321.  
  322.   ULONG len = strlen(ap->FuncName);
  323.  
  324.   if(!strcmp(ap->FuncName, "VFWritef") ||
  325.   !strcmp(ap->FuncName, "VFPrintf") ||
  326.   !strcmp(ap->FuncName, "VPrintf"))
  327.   {
  328.     if(!(ap->TagName = strndup(ap->FuncName+1, len-1)))
  329.       return 0;
  330.   }
  331.   else if(ap->FuncName[len-1] == 'A')
  332.   {
  333.     if(!strcmp(ap->FuncName+len-3, "DMA"))
  334.       return 1;
  335.     if(!(ap->TagName = strndup(ap->FuncName, len-1)))
  336.       return 0;
  337.   }
  338.   else if(!strcmp(ap->FuncName + len-7, "TagList"))
  339.   {
  340.     if(!(ap->TagName = strndup(ap->FuncName, len-3)))
  341.       return 0;
  342.     ap->TagName[len-4] = 's';
  343.   }
  344.   else if(!strcmp(ap->FuncName + len-4, "Args"))
  345.   {
  346.     if(!strcmp(ap->FuncName, "ReadArgs") || !strcmp(ap->FuncName, "FreeArgs"))
  347.       return 1;
  348.     if(!(ap->TagName = strndup(ap->FuncName, len-4)))
  349.       return 0;
  350.   }
  351.   else if(!stricmp(ap->Args[ap->NumArgs-1].ArgName, "tags") ||
  352.   !stricmp(ap->Args[ap->NumArgs-1].ArgName, "taglist"))
  353.   {
  354.     if(!(ap->TagName = strndup(ap->FuncName, len+4)))
  355.       return 0;
  356.     CopyMem("Tags", ap->TagName + len, 5);
  357.   }
  358.   else if(!stricmp(ap->Args[ap->NumArgs-1].ArgName, "args"))
  359.   {
  360.     if(!(ap->TagName = strndup(ap->FuncName, len+4)))
  361.       return 0;
  362.     CopyMem("Args", ap->TagName + len, 5);
  363.   }
  364.   return 1;
  365. }
  366.  
  367. void MakeLines(STRPTR buffer, ULONG size, ULONG test)
  368. {
  369.   ULONG a = 0;
  370.   if(size && buffer)
  371.   {
  372.     // make a real C++ zero string ending line
  373.     while(--size)
  374.     {
  375.       switch(*buffer)
  376.       {
  377.       case '(': ++a; break;
  378.       case ')': --a; break;
  379.       case '\n':
  380.         if(!test || !a)
  381.           *buffer = '\0';
  382.         else
  383.           *buffer = ' ';
  384.         break;
  385.       }
  386.       ++buffer;
  387.     }
  388.     *buffer = '\0';
  389.   }
  390. }
  391.  
  392. ULONG ScanFDFile(void)
  393. {
  394. #ifdef DEBUG_OLD
  395.   VPrintf("ScanFDFile:\n", 0);
  396. #endif
  397.  
  398.   ULONG _public = 1;
  399.   LONG bias = -1;
  400.   ULONG linenum, len;
  401.   STRPTR comment = 0;
  402.  
  403.   NewList((struct List *) &AmiPragmaList);
  404.  
  405.   for(linenum = 1; !CTRL_C && in.pos < in.buf + in.size; ++linenum)
  406.   {
  407.     if(*in.pos == '*')       /*  Comment   */
  408.     {
  409.       STRPTR oldpos = in.pos;
  410. #ifdef DEBUG_OLD
  411.   VPrintf("ScanFDFile: found a comment\n", 0);
  412. #endif
  413.       in.pos = SkipBlanks(in.pos+1);
  414.       if(!strnicmp(in.pos, "tagcall", 7))  /*  Tag to create?  */
  415.       {
  416.         struct AmiPragma *prevpragma = (struct AmiPragma *)
  417.         AmiPragmaList.mlh_TailPred;
  418.  
  419.     in.pos = SkipBlanks(in.pos + 7);
  420.     if(!prevpragma->Node.mln_Pred)
  421.     {
  422.       DoError(ERR_TAG_DEF_WITHOUT_PRAGMA, linenum);
  423.       ++in.pos;
  424.       continue;
  425.     }
  426.  
  427.     if(!prevpragma->NumArgs)
  428.     {
  429.       DoError(ERR_TAGFUNC_NEEDS_ARGUMENT, linenum);
  430.       ++in.pos;
  431.           continue;
  432.     }
  433.  
  434.     // Get the tag functions name.
  435.  
  436.     if(*in.pos)
  437.     {
  438.       STRPTR oldptr, tptr = prevpragma->TagName;
  439.  
  440.       len = strlen(prevpragma->FuncName)+strlen(in.pos)+1;
  441.       if(!(prevpragma->TagName = strndup(prevpragma->FuncName, len)))
  442.         return 0;
  443.  
  444.       if(*in.pos == '-')
  445.       {
  446.             STRPTR removeptr;
  447.  
  448.         oldptr = in.pos = SkipBlanks(in.pos+1);
  449.         in.pos = SkipName(in.pos);
  450.         if((len = in.pos-oldptr))
  451.         {
  452.               removeptr = prevpragma->TagName+strlen(prevpragma->TagName)-len;
  453.           if(!strncmp(removeptr, oldptr, len))
  454.           {
  455.         DoError(ERR_CANNOT_CONVERT_PRAGMA_TAGCALL, linenum);
  456.         prevpragma->TagName = tptr;
  457.         ++in.pos;
  458.                 continue;
  459.           }
  460.           *removeptr = '\0';
  461.         }
  462.         in.pos = SkipBlanks(in.pos);
  463.       }
  464.       if(*in.pos == '+')
  465.             in.pos = SkipBlanks(in.pos+1);
  466.  
  467.           *in.pos = toupper(*in.pos);
  468.  
  469.       in.pos = SkipName((oldptr = in.pos));
  470.       len = in.pos-oldptr;
  471.       if(len)
  472.       {
  473.             ULONG a = strlen(prevpragma->TagName);
  474.             CopyMem(oldptr, prevpragma->TagName+a, len);
  475.             prevpragma->TagName[a+len] = '\0';
  476.       }
  477.     }
  478.         else if(!prevpragma->TagName)
  479.         {
  480.           if(!(prevpragma->TagName = strndup(prevpragma->FuncName, len+4)))
  481.             return 0;
  482.           CopyMem("Tags", prevpragma->TagName + len, 5);
  483.         }
  484.       }
  485.       else
  486.       {
  487.     if(comment)
  488.           *(oldpos-1) = '\n';
  489.         else
  490.           comment = oldpos;
  491.         while(*in.pos)
  492.           ++in.pos;
  493.       }
  494.     }
  495.     else if(!strnicmp(in.pos, "##base", 6))
  496.     {
  497. #ifdef DEBUG
  498.   VPrintf("ScanFDFile: found ##base\n", 0);
  499. #endif
  500.       STRPTR oldptr;
  501.  
  502.       if(BaseName)
  503.         DoError(ERR_BASENAME_DECLARED_TWICE, linenum);
  504.  
  505.       in.pos = SkipBlanks(in.pos+6);
  506.       if(*in.pos != '_')
  507.     DoError(ERR_EXPECTED_SLASH_IN_BASENAME, linenum);
  508.       else
  509.         ++in.pos;
  510.  
  511.       in.pos = SkipName((oldptr = in.pos));
  512.       if((len = in.pos-oldptr))
  513.       {
  514.         if(!(BaseName = strndup(oldptr, len)))
  515.           return 0;
  516.     if(!ShortBaseName && !(ShortBaseName = strndup(BaseName, len-4)))
  517.           return 0;
  518.  
  519.         if(!(ShortBaseNameUpper = strndup(ShortBaseName, strlen(ShortBaseName))))
  520.           return 0;
  521.     else
  522.         {
  523.           STRPTR a = ShortBaseNameUpper;
  524.           while((*a = toupper(*a))) // Convert to uppercase
  525.             a++;
  526.         }
  527.       }
  528.       else
  529.     DoError(ERR_EXPECTED_BASENAME, linenum);
  530.     }
  531.     else if(!strnicmp(in.pos, "##bias", 6))
  532.     {
  533. #ifdef DEBUG
  534.   VPrintf("ScanFDFile: found ##bias\n", 0);
  535. #endif
  536.       STRPTR ptr;
  537.       LONG newbias;
  538.  
  539.       in.pos += 7;
  540.       newbias = strtol(in.pos, &ptr, 10);
  541.       if(ptr == in.pos)
  542.     DoError(ERR_EXPECTED_BIAS_VALUE, linenum);
  543.       else if(newbias < 0)
  544.       {
  545.     DoError(ERR_ASSUMING_POSITIVE_BIAS_VALUE, linenum);
  546.     bias = -newbias;
  547.       }
  548.       else
  549.     bias = newbias;
  550.       in.pos = SkipName(in.pos);
  551.     }
  552.     else if(!strnicmp(in.pos, "##end", 5))
  553.       break;
  554.     else if(!strnicmp(in.pos, "##public", 8))
  555.     {
  556.       in.pos += 8;
  557.       _public = 1;
  558.     }
  559.     else if(!strnicmp(in.pos, "##private", 9))
  560.     {
  561.       in.pos += 9;
  562.       _public = 0;
  563.     }
  564.     else
  565.     {
  566. #ifdef DEBUG_OLD
  567.   VPrintf("ScanFDFile: scan Function\n", 0);
  568. #endif
  569.       STRPTR oldptr;
  570.       struct AmiPragma *newpragma;
  571.       ULONG numargs;
  572.  
  573.       oldptr = in.pos = SkipBlanks(in.pos);
  574.       in.pos = SkipName(oldptr);
  575.       if(!(len = in.pos-oldptr))
  576.       {
  577.     DoError(ERR_MISSING_FUNCTION_NAME, linenum);
  578.     ++in.pos;
  579.     continue;
  580.       }
  581.       if(!(newpragma = (struct AmiPragma *) AllocRemember(&remember,
  582.       sizeof(struct AmiPragma), MEMF_ANY|MEMF_CLEAR)))
  583.         return 0;
  584.  
  585.       newpragma->FuncName = oldptr;
  586.       newpragma->Comment = comment;
  587.       comment = 0;
  588.  
  589.       in.pos = SkipBlanks(in.pos);
  590.       if(*in.pos != '(')
  591.       {
  592.     DoError(ERR_EXPECTED_OPEN_BRACKET, linenum);
  593.     ++in.pos;
  594.     continue;
  595.       }
  596.  
  597.       *in.pos = '\0'; // create c string of FunctionName
  598.  
  599. #ifdef DEBUG
  600.   VPrintf("ScanFDFile: found function %s\n", &newpragma->FuncName);
  601. #endif
  602.  
  603.       do
  604.       {
  605.         oldptr = in.pos = SkipBlanks(in.pos+1);
  606.  
  607.     if(*in.pos == ')' && !newpragma->NumArgs)
  608.       break;
  609.  
  610.     if(newpragma->NumArgs == 14)
  611.         {
  612.       DoError(ERR_TO_MUCH_ARGUMENTS, linenum); break;
  613.         }
  614.  
  615.     in.pos = SkipName(oldptr);
  616.         if(*in.pos == '*')
  617.           ++in.pos;
  618.     if(!(len = in.pos-oldptr))
  619.     {
  620.       DoError(ERR_EXPECTED_ARGUMENT_NAME, linenum);
  621.       break;
  622.     }
  623.  
  624.     newpragma->Args[newpragma->NumArgs++].ArgName = oldptr;
  625.     oldptr = in.pos;
  626.  
  627.     in.pos = SkipBlanks(in.pos);
  628.     if(*in.pos != ',' && *in.pos != '/' && *in.pos != ')')
  629.     {
  630.       DoError(ERR_EXPECTED_CLOSE_BRACKET, linenum);
  631.       break;
  632.     }
  633.     if(*in.pos != ')') // create c string ending
  634.       *oldptr = '\0';
  635.       }
  636.       while(*in.pos != ')');
  637.       if(*in.pos != ')')
  638.       {
  639.         while(*(in.pos++))
  640.           ++in.pos;
  641.         continue;
  642.       }
  643.       else
  644.         *oldptr = '\0';    // create c string ending for last argument
  645.     
  646.       if(*(in.pos = SkipBlanks(in.pos+1)) != '(')
  647.       {
  648.         DoError(ERR_EXPECTED_OPEN_BRACKET, linenum);
  649.     ++in.pos;
  650.     continue;
  651.       }
  652.  
  653.       numargs = 0;
  654.       do
  655.       {
  656.         ULONG i;
  657.  
  658.     oldptr = in.pos = SkipBlanks(in.pos + 1);
  659.  
  660.     if(*in.pos == ')' && numargs == 0)
  661.       break;
  662.  
  663.     in.pos = SkipName(oldptr);
  664.     len = in.pos-oldptr;
  665.  
  666.     for(i = 0; i < 16; i++)
  667.           if(!strnicmp(RegNames[i], oldptr, len))
  668.         break;
  669.  
  670.     if(i == 16)
  671.     {
  672.       DoError(ERR_EXPECTED_REGISTER_NAME, linenum);
  673.       break;
  674.     }
  675.     if(i > 14)
  676.     {
  677.       DoError(ERR_ILLEGAL_REGISTER, linenum);
  678.       break;
  679.     }
  680.  
  681.     newpragma->Args[numargs].ArgReg = i;
  682.  
  683.     for(i = 0; i < numargs; i++)
  684.     {
  685.           if(newpragma->Args[numargs].ArgReg == newpragma->Args[i].ArgReg)
  686.       {
  687.         DoError(ERR_REGISTER_USED_TWICE, linenum);
  688.         break;
  689.       }
  690.     }
  691.         if(i < numargs)
  692.           break;
  693.  
  694.     ++numargs;
  695.  
  696.     in.pos = SkipBlanks(in.pos);
  697.     if(*in.pos != ',' && *in.pos != '/' && *in.pos != ')')
  698.     {
  699.       DoError(ERR_EXPECTED_CLOSE_BRACKET, linenum);
  700.       break;
  701.     }
  702.       }
  703.       while(*in.pos != ')');
  704.       if(*in.pos != ')')
  705.       {
  706.         while(*(in.pos++))
  707.           ++in.pos;
  708.         continue;
  709.       }
  710.       else
  711.         ++in.pos;
  712.  
  713.       if(!MakeTagFunction(newpragma))
  714.         return 0;
  715.  
  716.       if(numargs != newpragma->NumArgs)
  717.       {
  718.     DoError(ERR_AGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER, linenum);
  719.         newpragma->NumArgs = numargs;
  720.       }
  721.  
  722.       if(bias == -1)
  723.       {
  724.     DoError(ERR_ASSUMING_BIAS_OF_30, linenum);
  725.     bias = 30;
  726.       }
  727.       newpragma->Bias = bias;
  728.       bias += 6;
  729.  
  730.       newpragma->Public = _public;
  731.  
  732.       AddTail((struct List *) &AmiPragmaList, (struct Node *) newpragma);
  733.     }
  734.  
  735.     in.pos = SkipBlanks(in.pos);
  736.     if(*in.pos)
  737.       DoError(ERR_EXTRA_CHARACTERS, linenum);
  738.     ++in.pos; // skip '\0'
  739.   }
  740.  
  741.   if(!BaseName)
  742.   {
  743.     DoError(ERR_MISSING_BASENAME, 0); return 0;
  744.   }
  745.  
  746.   if(CTRL_C)
  747.     return 0;
  748.   return 1;
  749. }
  750.  
  751. ULONG WriteHeader(void)
  752. {
  753.   ULONG a = 0;
  754.   switch(MODE)
  755.   {
  756.   case 1: a = DoOutput("#ifndef _INCLUDE_PRAGMA_%s_LIB_H\n#define _INCLUDE_PRAGMA_%s_LIB_H"
  757.     "\n\n#ifndef CLIB_%s_PROTOS_H\n#include <clib/%s_protos.h>\n#endif\n\n", ShortBaseNameUpper,
  758.     ShortBaseNameUpper, ShortBaseNameUpper, ShortBaseName); break;
  759.   case 2: a = DoOutput("#ifndef PRAGMAS_%s_LIB_H\n#define PRAGMAS_%s_LIB_H"
  760.     "\n\n#ifndef CLIB_%s_PROTOS_H\n#include <clib/%s_protos.h>\n#endif\n\n", ShortBaseNameUpper,
  761.     ShortBaseNameUpper, ShortBaseNameUpper, ShortBaseName); break;
  762.   case 3: a = DoOutput("#ifndef PRAGMAS_%s_PRAGMAS_H\n#define PRAGMAS_%s_PRAGMAS_H"
  763.     "\n\n#ifndef CLIB_%s_PROTOS_H\n#include <clib/%s_protos.h>\n#endif\n\n", ShortBaseNameUpper,
  764.     ShortBaseNameUpper, ShortBaseNameUpper, ShortBaseName); break;
  765.   case 4: return 1;
  766.   }
  767.   return a;
  768. }
  769.  
  770. ULONG WriteFooter(void)
  771. {
  772.   ULONG a = 0;
  773.   switch(MODE)
  774.   {
  775.   case 1: a = DoOutput("\n#endif\t/*  _INCLUDE_PRAGMA_%s_LIB_H  */",
  776.     ShortBaseNameUpper); break;
  777.   case 2: a = DoOutput("\n#endif\t/*  PRAGMAS_%s_LIB_H  */",
  778.     ShortBaseNameUpper); break;
  779.   case 3: a = DoOutput("\n#endif\t/*  PRAGMAS_%s_PRAGMA_H  */",
  780.     ShortBaseNameUpper); break;
  781.   case 4: return 1;
  782.   }
  783.   return a;
  784. }
  785.  
  786. /*
  787.     This function writes one amicall pragma.
  788.  
  789.     Inputs: Ap    - a pointer to the pragma which should be written.
  790.         TagCall - TRUE for a tagcall pragma, FALSE for a libcall pragma
  791.  
  792.     Result: TRUE, if successful, FALSE otherwise
  793. */
  794.  
  795. ULONG WritePragmaAMICALL(struct AmiPragma *Ap, ULONG TagCall)
  796. {
  797.   ULONG i;
  798.  
  799.   if(!DoOutput("#pragma %s(%s,0x%03lx,%s("/*))*/, TagCall ? "tagcall" :
  800.   "amicall", BaseName, Ap->Bias, TagCall ? Ap->TagName : Ap->FuncName))
  801.     return 0;
  802.  
  803.   for(i = 0; i < Ap->NumArgs; ++i)
  804.   {
  805.     if(!DoOutputDirect(RegNames[Ap->Args[i].ArgReg], 2) ||
  806.     (i+1 < Ap->NumArgs && !DoOutput(",")))
  807.       return 0;
  808.   }
  809.  
  810.   return DoOutput(/*((*/"))\n");
  811. }
  812.  
  813. /*
  814.     This function writes one pragma for SAS-C.
  815.  
  816.     Inputs: Ap        - a pointer to the pragma which should be written.
  817.         TagCall - TRUE for a tagcall pragma, FALSE for a libcall pragma
  818.  
  819.     Result: TRUE, if successful, FALSE otherwise
  820. */
  821.  
  822. ULONG WritePragmaLIBCALL(struct AmiPragma *Ap, ULONG TagCall)
  823. {
  824.   LONG i;
  825.  
  826.   if((Flags & FLAG_SYSCALL) && !strcmp(BaseName,"SysBase"))
  827.   {
  828.     if(!DoOutput("#pragma syscall %-20s %03lx ", Ap->FuncName, Ap->Bias))
  829.       return 0;
  830.   }
  831.   else
  832.   {
  833.     if(!DoOutput("#pragma %s %s %-20s %03lx ", TagCall ? "tagcall" :
  834.     "libcall", BaseName, TagCall ? Ap->TagName : Ap->FuncName, Ap->Bias))
  835.       return 0;
  836.   }
  837.  
  838.   for(i = Ap->NumArgs-1; i >= 0; --i)
  839.     if(!DoOutput("%lx",Ap->Args[i].ArgReg))
  840.       return 0;
  841.  
  842.   return DoOutput("0%lx\n", Ap->NumArgs);
  843. }
  844.  
  845. STRPTR FindClibFunc(STRPTR func) // finds the needed function
  846. {
  847. #ifdef DEBUG
  848.   VPrintf("FindClibFunc: %s\n", &func);
  849. #endif
  850.  
  851.   ULONG len = strlen(func);
  852.   STRPTR string, linestart, strend = clibbuf + clibsize;
  853.  
  854.   if(!(linestart = string = clibbuf))
  855.     return 0;
  856.  
  857.   do
  858.   {
  859.     while(*string && *string != '(')
  860.       ++string;
  861.     if(*string == '(')
  862.     {
  863.       while(*(--string) == ' ' || *string == '\t')
  864.         ;
  865.       if(!strncmp(func, string-len+1, len))
  866.         return linestart;
  867.     }
  868.     while(string < strend && *string)
  869.       ++string;
  870.     if(!*string)
  871.       linestart = ++string;
  872.   } while(string < strend);
  873.   
  874.   return 0;
  875. }
  876.  
  877. ULONG GetClibLength(STRPTR start) // returns length of the type
  878. {
  879. #ifdef DEBUG
  880.   VPrintf("GetClibLength:\n", 0);
  881. #endif
  882.   STRPTR old = start;
  883.   ULONG a = 1;
  884.  
  885.   while(a)
  886.   {
  887.     start = SkipBlanks(start); a = 0;
  888.     if(!strncmp("const",start, 5))
  889.     {
  890.       ++a; start += 6;
  891.     }
  892.     if(!strncmp("struct",start,6) || !strncmp("signed", start,6))
  893.     {
  894.       ++a; start += 7;
  895.     }
  896.     if(!strncmp("unsigned",start,8))
  897.     {
  898.       ++a; start += 9;
  899.     }
  900.   }
  901.  
  902.   while(*start && *start != ' ' && *start != '\t' && *start != '*')
  903.    ++start;
  904.  
  905.   {
  906.     STRPTR u = SkipBlanks(start);
  907.     if(*u == '*')
  908.       start = u+1;
  909.   }
  910.  
  911.   return (ULONG) (start-old);
  912. }
  913.  
  914. ULONG OutClibType(STRPTR start)
  915. {
  916. #ifdef DEBUG
  917.   VPrintf("OutClibType:\n", 0);
  918. #endif
  919.   UBYTE string[11];
  920.   ULONG length = GetClibLength(start), i;
  921.  
  922.   while(length)
  923.   {
  924.     if(length > 10)
  925.       i = 10;
  926.     else
  927.       i = length;
  928.  
  929.     CopyMem(start, string, i);
  930.     string[i] = '\0'; length -= i; start += i;
  931.     if(!DoOutput(string))
  932.       return 0;
  933.   }
  934.   return 1;
  935. }
  936.  
  937. UBYTE deftype[] = "ULONG";
  938.  
  939. STRPTR GetClibType(STRPTR start) // searches for next type definition
  940. {
  941.   if(start == deftype)
  942.     return start;
  943. #ifdef DEBUG
  944.   VPrintf("GetClibType:\n", 0);
  945. #endif
  946.   while(*start && *start != '(' && *start != ',' && *start != ')')
  947.     ++start;
  948.   if(!*start || *start == /*(*/')')
  949.     return 0;
  950.   return SkipBlanks(++start);
  951. }
  952.  
  953. ULONG CreateCSTUBS(struct AmiPragma *ap, ULONG TagCall)
  954. {
  955.   STRPTR string,str2,lastarg;
  956.   STRPTR ret = "return ";
  957.   ULONG i;
  958.  
  959.   str2 = FindClibFunc(ap->TagName);
  960.   if(!(string = FindClibFunc(ap->FuncName)))
  961.     string = deftype;
  962.  
  963.   string = SkipBlanks(string);
  964.   if(!strnicmp("void", string, 4))
  965.     ret = 0;
  966.  
  967.   if(!OutClibType(string) || !DoOutput(" %s("/*)*/, ap->TagName))
  968.     return 0;
  969.   for(i = 0; i < ap->NumArgs-1; i++)
  970.   {
  971.     str2 = GetClibType(str2); // skip the equal parts
  972.     if(!(string = GetClibType(string)) || !OutClibType(string) ||
  973.     !DoOutput(" %s, ", ap->Args[i].ArgName))
  974.       return 0;
  975.   }
  976.   lastarg = string;
  977.   if((str2 = GetClibType(str2)))
  978.   {
  979.     if(!strncmp("...", str2, 3))
  980.       str2 = 0;
  981.     else if(!OutClibType(str2) || !DoOutput(" %s, ", ap->Args[i].ArgName))
  982.       return 0;
  983.   }
  984.  
  985.   if(!DoOutput(/*(*/"...)\n{\n  %s%s("/*)*/, ret, ap->FuncName))
  986.     return 0;
  987.   for(i = 0; i < ap->NumArgs-1; i++)
  988.   {
  989.     if(!DoOutput("%s, ", ap->Args[i].ArgName))
  990.       return 0;
  991.   }
  992.   if(!DoOutput("("/*)*/) || !(string = GetClibType(string)) ||
  993.   !OutClibType(string))
  994.     return 0;
  995.   if(str2)
  996.   {
  997.     if(!DoOutput(/*((*/") &%s);\n}\n", ap->Args[ap->NumArgs-1].ArgName))
  998.       return 0;
  999.   }
  1000.   else if (!DoOutput(/*(*/") ((ULONG) &%s + sizeof("/*))*/,
  1001.   ap->Args[ap->NumArgs-2].ArgName) || !OutClibType(lastarg) ||
  1002.   !DoOutput(/*(((*/")));\n}\n"))
  1003.     return 0;
  1004.   return 1;
  1005. }
  1006.  
  1007. ULONG CallPrag(STRPTR type, ULONG tagmode,
  1008. ULONG (*CallFunc) (struct AmiPragma *, ULONG))
  1009. {
  1010.   struct AmiPragma *ap;
  1011.   ULONG tagcall_seen = 1;
  1012.   if(type)
  1013.   {
  1014.     if(*type && !DoOutput("#if%s\n",type))
  1015.       return 0;
  1016.     for(ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  1017.     ap->Node.mln_Succ && !CTRL_C;
  1018.     ap = (struct AmiPragma *) ap->Node.mln_Succ)
  1019.     {
  1020.       if(ap->Public)
  1021.       {
  1022.     if(!tagmode && ap->Comment && (Flags & FLAG_DOCOMMENT) &&
  1023.         !DoOutput("/%s */\n", ap->Comment))
  1024.           return 0;
  1025.         if((tagmode ? ap->TagName : ap->FuncName) && !CallFunc(ap, tagmode))
  1026.           return 0;
  1027.         if(ap->TagName)
  1028.       ++tagcall_seen;
  1029.       }
  1030.     }
  1031.     if(*type && !DoOutput("#endif\n"))
  1032.       return 0;
  1033.     if(CTRL_C)
  1034.       return 0;
  1035.   }
  1036.   return tagcall_seen;
  1037. }
  1038.  
  1039. ULONG CreatePragmaFile(void)
  1040. {
  1041.   ULONG result;
  1042.   ULONG tagcall_seen = 0;
  1043.  
  1044.   if(!WriteHeader())
  1045.     return 0;
  1046.  
  1047.   if((Flags & FLAG_PROTOTYPE) && !DoOutput("extern struct Library *%s;\n\n",
  1048.   BaseName))
  1049.     return 0;  
  1050.  
  1051.   if((Flags & FLAG_EXTERNC) &&
  1052.   !DoOutput("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"))
  1053.     return 0;
  1054.  
  1055.   if(!(result = CallPrag(AMICALL, 0, WritePragmaAMICALL)))
  1056.     return 0;
  1057.   tagcall_seen += result - 1;
  1058.   if(!(result = CallPrag(LIBCALL, 0, WritePragmaLIBCALL)))
  1059.     return 0;
  1060.   tagcall_seen += result - 1;
  1061.  
  1062.   if(((!AMICALL && !LIBCALL) || tagcall_seen) && (AMITAGS || LIBTAGS || CSTUBS))
  1063.   {
  1064.     if(!DoOutput("\n") || !CallPrag(AMITAGS, 1, WritePragmaAMICALL) ||
  1065.     !CallPrag(LIBTAGS, 1, WritePragmaLIBCALL) ||
  1066.     !CallPrag(CSTUBS, 1, CreateCSTUBS))
  1067.       return 0;
  1068.    }
  1069.  
  1070.   if((Flags & FLAG_EXTERNC) &&
  1071.   !DoOutput("\n#ifdef __cplusplus\n}\n#endif\n"))
  1072.     return 0;
  1073.  
  1074.   return WriteFooter();
  1075. }
  1076.  
  1077. ULONG CreateLVOFile(ULONG mode)
  1078. {
  1079.   struct AmiPragma *ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  1080.  
  1081.   {
  1082.     STRPTR data = "_LVO_I";
  1083.  
  1084.     if(mode == 2 || mode == 4)
  1085.       data = "_LIB_I";
  1086.  
  1087.     if(!DoOutput("\t\tIFND LIBRARIES_%s%s\nLIBRARIES_%s%s\tSET\t1\n\n",
  1088.     ShortBaseNameUpper, data, ShortBaseNameUpper, data))
  1089.       return 0;
  1090.   }
  1091.  
  1092.   if(mode <= 2)
  1093.   {
  1094.     for(; !CTRL_C && ap->Node.mln_Succ; ap = (struct AmiPragma *) ap->Node.mln_Succ)
  1095.     {
  1096.       if(ap->Public && !DoOutput("\t\tXDEF\t_LVO%s\n", ap->FuncName))
  1097.         return 0;
  1098.     }
  1099.   }
  1100.  
  1101.   for(ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  1102.   !CTRL_C && ap->Node.mln_Succ;
  1103.   ap = (struct AmiPragma *) ap->Node.mln_Succ)
  1104.   {
  1105.     if(ap->Public && !DoOutput("\n_LVO%-24s\tEQU\t-%ld", ap->FuncName, ap->Bias))
  1106.       return 0;
  1107.   }
  1108.  
  1109.   if(!DoOutput("\n\n\t\tENDC"))
  1110.     return 0;
  1111.  
  1112.   if(CTRL_C)
  1113.     return 0;
  1114.  
  1115.   return 1;
  1116. }
  1117.  
  1118. ULONG DoAsmText(STRPTR text, struct AmiPragma *ap)
  1119. {
  1120.   ULONG i;
  1121.  
  1122.   if(!DoOutput("\n\tXDEF\t_%s\n_%s:\n\tMOVE.L\tA6,-(A7)\n\tMOVE.L\t_%s,A6\n",
  1123.   text, text, BaseName))
  1124.     return 0;
  1125.   for(i = 0; i < ap->NumArgs; ++i)
  1126.   {
  1127.     if(!DoOutput("\tMOVE.L\t%02ld(A7),%s\n", (i+2)<<2,
  1128.     RegNames[ap->Args[i].ArgReg]))
  1129.       return 0;
  1130.   }
  1131.   if(!DoOutput("\tJSR\t-%03ld(A6)\n\tMOVE.L\t(A7)+,A6\n\tRTS\n",ap->Bias))
  1132.     return 0;
  1133.   
  1134.   return 1;
  1135. }
  1136.  
  1137. ULONG DoAsmCode(STRPTR text, struct AmiPragma *ap)
  1138. {
  1139.   ULONG a[5], i = strlen(ShortBaseNameUpper);
  1140.  
  1141.   a[0] = HUNK_UNIT; a[1] = 0; a[2] = HUNK_NAME;
  1142.   a[3] = (i + 6 + 3)>>2;
  1143.  
  1144.   if(!DoOutputDirect(a, 16) || !DoOutputDirect(ShortBaseNameUpper, i) ||
  1145.   !DoOutputDirect("_STUBS\0\0\0", (a[3]<<2)-i))
  1146.     return 0;
  1147.  
  1148.   a[0] = HUNK_CODE; a[1] = ap->NumArgs+4; a[2] = 0x2F0E2C79, a[3] = 0;
  1149.  
  1150.   if(!DoOutputDirect(a, 16))
  1151.     return 0;
  1152.  
  1153.   for(i = 0; i < ap->NumArgs; ++i) // MOVE.L code generieren
  1154.   {
  1155.     ULONG j;
  1156.  
  1157.     a[0] = 0x202F0000 + ((i+2)<<2);
  1158.  
  1159.     j = ap->Args[i].ArgReg;
  1160.     if(j > 7)
  1161.     {
  1162.       a[0] |= 0x400000; j -= 8;    // set MOVEA bit
  1163.     }
  1164.     a[0] |= j << 25;        // set destination register
  1165.  
  1166.     if(!DoOutputDirect(a, 4))
  1167.       return 0;
  1168.   }
  1169.  
  1170.   // here comes the base reference
  1171.   a[0] = 0x4EAE0000 + (UWORD) (- ap->Bias); //JSR instruction
  1172.   a[1] = 0x2C5F4E75; a[2] = HUNK_EXT;
  1173.   a[3] = 0x81000000 + ((strlen(BaseName) + 1 + 3)>>2);
  1174.   a[4] = 0x5F000000;
  1175.  
  1176.   if(!DoOutputDirect(a, 17) || 
  1177.   !DoOutputDirect(BaseName, (((UWORD) a[3])<<2)-1))
  1178.     return 0;
  1179.  
  1180.   // here comes the XDEF name reference
  1181.   a[0] = 1; a[1] = 4; a[2] = 0x01000000+((strlen(text) + 1 + 3)>>2);
  1182.   a[3] = 0x5F000000;
  1183.  
  1184.   if(!DoOutputDirect(a, 13) || !DoOutputDirect(text, (((UWORD) a[2])<<2)-1))
  1185.     return 0;
  1186.  
  1187.   a[0] = 0; a[1] = 0; a[2] = HUNK_END;
  1188.  
  1189.   return DoOutputDirect(a, 12);
  1190. }
  1191.  
  1192. ULONG CreateAsmStubs(ULONG TagCall)
  1193. {
  1194.   struct AmiPragma *ap;
  1195.  
  1196.   if(TagCall <= 2 && !DoOutput("\tSECTION\t \"%s_STUBS\",CODE\n\tXREF\t_%s\n",
  1197.   ShortBaseNameUpper, BaseName))
  1198.     return 0;
  1199.  
  1200.   for(ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  1201.   !CTRL_C && ap->Node.mln_Succ;
  1202.   ap = (struct AmiPragma *) ap->Node.mln_Succ)
  1203.   {
  1204.     if(ap->Public)
  1205.     {
  1206.       if(TagCall <= 2)
  1207.       {
  1208.         if(TagCall == 1 && !DoAsmText(ap->FuncName, ap))
  1209.           return 0;
  1210.         if(ap->TagName && !DoAsmText(ap->TagName, ap))
  1211.           return 0;
  1212.       }
  1213.       else
  1214.       {
  1215.         if(TagCall == 3 && !DoAsmCode(ap->FuncName, ap))
  1216.           return 0;
  1217.         else if(ap->TagName && !DoAsmCode(ap->TagName, ap))
  1218.           return 0;
  1219.       }
  1220.     }
  1221.   }
  1222.  
  1223.   if(CTRL_C)
  1224.     return 0;
  1225.   return 1;
  1226. }
  1227.  
  1228. ULONG CreateProtoFile(ULONG Type)
  1229. {
  1230.   if(!DoOutput("#ifndef _PROTO_%s_H\n#define _PROTO_%s_H\n\n#include "
  1231.     "<exec/types.h>\n\nextern struct Library *%s;\n\n#include <clib/"
  1232.     "%s_protos.h>\n#include <%s/%s_%s.h>\n\n#endif\n", ShortBaseNameUpper,
  1233.     ShortBaseNameUpper,BaseName,ShortBaseName,
  1234.     (Type <= 2 ? "pragma" : "pragmas"), ShortBaseName,
  1235.     (Type & 1 ? "lib" : "pragmas")))
  1236.     return 0;
  1237.   return 1;
  1238. }
  1239.  
  1240. void WriteError(void)
  1241. {
  1242.   DoError(ERR_WRITING_FILE, 0);
  1243.   End(RETURN_FAIL);
  1244. }
  1245.  
  1246. STRPTR helptext =
  1247. "FDFILE:  the fd file which should be used\n"
  1248. "SPECIAL: 1 - Aztec Compiler (xxx_lib.h,     MODE 2, AMICALL)\n"
  1249. "\t 2 - DICE Compiler  (xxx_pragmas.h, MODE 3, LIBCALL)\n"
  1250. "\t 3 - SAS Compiler   (xxx_pragmas.h, MODE 3, LIBCALL,LIBTAGS)\n"
  1251. "\t 4 - MAXON Compiler (xxx_lib.h,     MODE 1, AMICALL,EXTERNC)\n"
  1252. "\t 5 - STORM Compiler (xxx_lib.h,     MODE 1, AMITAGS,AMICALL,EXTERNC)\n"
  1253. "\t 6 - All Compilers\n"
  1254. "\t 7 - Assembler lvo _lvo.i file\n"
  1255. "\t 8 - Assembler lvo _lib.i file\n"
  1256. "\t 9 - Assembler lvo _lvo.i file no XDEF\n"
  1257. "\t10 - Assembler lvo _lib.i file no XDEF\n"
  1258. "\t11 - all assembler Stub-functions\n"
  1259. "\t12 - Tagcall assembler Stub-functions\n"
  1260. "\t13 - all assembler Stub-function code library\n"
  1261. "\t14 - Tagcall assembler Stub-function code library\n"
  1262. "\t15 - Proto file with pragma/..._lib.h call\n"
  1263. "\t16 - Proto file with pragma/..._pragmas.h call\n"
  1264. "\t17 - Proto file with pragmas/..._lib.h call\n"
  1265. "\t18 - Proto file with pragmas/..._pragmas.h call\n"
  1266. "TO:\t the destination directory (self creation of filename) or\n"
  1267. "\t the destination file\n"
  1268. "COMMENT: enables addition of comments found in fd file.\n"
  1269. "MODE:\t 1 - _INCLUDE_PRAGMA_..._LIB_H definition method\n"
  1270. "\t 2 - _PRAGMAS_..._LIB_H definition method\n"
  1271. "\t 3 - _PRAGMAS_..._PRAGMAS_H definition method\n"
  1272. "\t 4 - no definition\n"
  1273. "AMICALL: creates amicall pragmas\n"
  1274. "LIBCALL: creates libcall pragmas\n"
  1275. "AMITAGS: creates tagcall pragmas (amicall like method (StormC++))\n"
  1276. "LIBTAGS: creates tagcall pragmas (libcall like method (StormC++))\n"
  1277. "CSTUBS:  creates stub functions in c code\n"
  1278. "The last five need a string as argument. This string is used to set\n"
  1279. "a #if (given string) before the set method.\n"
  1280. "EXTERNC: add an #ifdef __cplusplus ... statement to pragma file.\n"
  1281. "USESYSCALL: uses syscall pragma instead of libcall ExecBase.\n"
  1282. "CLIB:    name of the clib-proto file (used for CSTUBS).";
  1283.  
  1284. void main(void)
  1285. {
  1286.   UBYTE filename[255];    // needed for filename
  1287.   struct
  1288.   {
  1289.     STRPTR FDFILE;
  1290.     ULONG* SPECIAL;
  1291.     STRPTR TO;
  1292.     ULONG  COMMENT;
  1293.     ULONG* MODE;
  1294.     STRPTR AMICALL;
  1295.     STRPTR LIBCALL;
  1296.     STRPTR AMITAGS;
  1297.     STRPTR LIBTAGS;
  1298.     STRPTR CSTUBS;
  1299.     ULONG  EXTERNC;
  1300.     ULONG  USESYSCALL;
  1301.     STRPTR CLIB;
  1302.   } args = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  1303.  
  1304. #ifdef __SASC    // with __MAXON__ this is done automatic by my StartUp
  1305.   TestOS;
  1306. #endif
  1307.  
  1308.   if(!(rda = (struct RDArgs *) AllocDosObject(DOS_RDARGS, 0)))
  1309.     End(RETURN_FAIL);
  1310.   rda->RDA_ExtHelp = helptext;
  1311.   if(!ReadArgs(PARAM, (LONG *) &args, rda) ||
  1312.   !(in.file = Open(args.FDFILE, MODE_OLDFILE)) ||
  1313.   !(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 37)) ||
  1314.   !(fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, 0)) ||
  1315.   !ExamineFH(in.file, fib) ||
  1316.   !(in.buf = in.pos = (STRPTR) AllocRemember(&remember, (in.size = fib->fib_Size)+1, MEMF_ANY)) ||
  1317.   Read(in.file, in.buf, in.size) != in.size ||
  1318.   !(out.buf = out.pos = (STRPTR) AllocRemember(&remember, out.size, MEMF_ANY)))
  1319.     End(RETURN_FAIL);
  1320.  
  1321.   {
  1322.     STRPTR ptr = FilePart(args.FDFILE);
  1323.     LONG len = strlen(ptr)-7;
  1324.     if(len >= 0 && !stricmp(ptr+len, "_lib.fd"))
  1325.     {
  1326.       ShortBaseName = ptr;
  1327.       ptr[len] = '\0';
  1328.     }
  1329.   }
  1330.  
  1331.   Close(in.file); in.file = 0;
  1332.  
  1333.   if(args.CLIB)
  1334.   {
  1335.     if(!(in.file = Open(args.CLIB, MODE_OLDFILE)) ||
  1336.     !ExamineFH(in.file, fib) ||
  1337.     !(clibbuf = (STRPTR) AllocRemember(&remember, (clibsize = fib->fib_Size)+1, MEMF_ANY)) ||
  1338.     Read(in.file, clibbuf, clibsize) != clibsize)
  1339.       End(RETURN_FAIL);
  1340.   }
  1341.  
  1342.   MakeLines(in.pos, in.size, 0);
  1343.   MakeLines(clibbuf, clibsize, 1);
  1344.  
  1345.   if(!ScanFDFile())
  1346.     End(RETURN_FAIL);
  1347.  
  1348.   if(args.TO)
  1349.   {
  1350.     if((lock = Lock(args.TO, SHARED_LOCK)) && Examine(lock, fib) &&
  1351.     fib->fib_DirEntryType > 0)
  1352.     {
  1353.       oldfh = CurrentDir(lock);
  1354.       args.TO = 0;
  1355.     }
  1356.     else if(lock)
  1357.     {
  1358.       UnLock(lock);
  1359.       lock = 0;
  1360.     }
  1361.   }
  1362.  
  1363.   sprintf(filename, "%s_lib.h", ShortBaseName);
  1364.  
  1365.   if(args.TO)
  1366.     DESTFILE = args.TO;
  1367.   if(args.SPECIAL && *args.SPECIAL > 0 && *args.SPECIAL < 19)
  1368.   {
  1369.     switch(*args.SPECIAL)
  1370.     {
  1371.       case 1: MODE = 2; AMICALL = ""; break;
  1372.       case 2: sprintf(filename, "%s_pragmas.h", ShortBaseName);
  1373.               MODE = 3; LIBCALL = ""; Flags |= FLAG_PROTOTYPE; break;
  1374.       case 3: sprintf(filename, "%s_pragmas.h", ShortBaseName);
  1375.               MODE = 3; LIBCALL = ""; LIBTAGS = "def " TEXT_SAS_60; break;
  1376.       case 4: MODE = 1; AMICALL = ""; Flags |= FLAG_EXTERNC; break;
  1377.       case 5: MODE = 1; AMICALL = AMITAGS = ""; Flags |= FLAG_EXTERNC; break;
  1378.       case 6: MODE = 1; AMICALL = " defined(" TEXT_AZTEC ") || defined("
  1379.     TEXT_MAXON ") || defined(" TEXT_STORM ")"; Flags |= FLAG_EXTERNC;
  1380.     LIBCALL = " defined(" TEXT_DICE ") || defined(" TEXT_SAS ")";
  1381.     LIBTAGS = "def " TEXT_SAS_60; AMITAGS ="def " TEXT_STORM; break;
  1382.  
  1383.       case 7: case 9: MODE = 100+*args.SPECIAL-7;
  1384.         sprintf(filename, "%s_lvo.i", ShortBaseName); break;
  1385.       case 8: case 10: MODE = 100+*args.SPECIAL-7;
  1386.         sprintf(filename, "%s_lib.i", ShortBaseName); break;
  1387.       case 11: case 12: MODE = 200+*args.SPECIAL-11;
  1388.         sprintf(filename, "%s_stub.a", ShortBaseName); break;
  1389.       case 13: case 14: MODE = 200+*args.SPECIAL-11;
  1390.         sprintf(filename, "%s.lib", ShortBaseName); break;
  1391.       case 15: case 16: case 17: case 18: MODE = 300+*args.SPECIAL-15;
  1392.         sprintf(filename, "%s.h", ShortBaseName); break;
  1393.     }
  1394.     if(!DESTFILE)
  1395.       DESTFILE = filename;
  1396.   }
  1397.   if(args.EXTERNC)
  1398.     Flags ^= FLAG_EXTERNC;
  1399.   if(args.USESYSCALL)
  1400.     Flags ^= FLAG_SYSCALL;
  1401.   if(args.COMMENT)
  1402.     Flags ^= FLAG_DOCOMMENT;
  1403.  
  1404.   if(args.MODE && *args.MODE > 0 && *args.MODE < 5)
  1405.     MODE = *args.MODE;
  1406.   if(args.AMICALL)
  1407.     AMICALL = args.AMICALL;
  1408.   if(args.LIBCALL)
  1409.     LIBCALL = args.LIBCALL;
  1410.   if(args.AMITAGS)
  1411.     AMITAGS = args.AMITAGS;
  1412.   if(args.LIBTAGS)
  1413.     LIBTAGS = args.LIBTAGS;
  1414.   if(args.CSTUBS)
  1415.     CSTUBS = args.CSTUBS;
  1416.  
  1417.   if(!CSTUBS && !AMITAGS && !AMICALL && !LIBTAGS && !LIBCALL && MODE < 100)
  1418.   {
  1419.     SetIoErr(ERROR_REQUIRED_ARG_MISSING);
  1420.     End(RETURN_FAIL);
  1421.   }
  1422.  
  1423.   if(!DESTFILE)
  1424.   {
  1425.     DoError(ERR_NO_FILENAME, 0);
  1426.     End(RETURN_FAIL);
  1427.   }
  1428.  
  1429.   if(!(out.file = Open(DESTFILE, MODE_NEWFILE)))
  1430.     End(RETURN_FAIL);
  1431.  
  1432.   SetIoErr(0);
  1433.  
  1434.   if(MODE >= 300)
  1435.   {
  1436.     if(!CreateProtoFile(MODE-299))
  1437.       WriteError();
  1438.   }
  1439.   else if(MODE >= 200)
  1440.   {
  1441.     if(!CreateAsmStubs(MODE-199))
  1442.       WriteError();
  1443.   }
  1444.   else if(MODE >= 100)
  1445.   {
  1446.     if(!CreateLVOFile(MODE - 99))
  1447.       WriteError();
  1448.   }
  1449.   else if(AMICALL || AMITAGS || LIBCALL || LIBTAGS || CSTUBS)
  1450.   {
  1451.     if(!CreatePragmaFile())
  1452.       WriteError();
  1453.   }
  1454.   else
  1455.     End(RETURN_FAIL);
  1456.  
  1457.   End(RETURN_OK);
  1458. }
  1459.  
  1460. void end(void)
  1461. {
  1462.   if(fib)        FreeDosObject(DOS_FIB, fib);
  1463.   if(in.file)        Close(in.file);
  1464.   if(out.file)
  1465.   {
  1466.     Out(out.size);    // clears Output-Buffer
  1467.     Close(out.file);
  1468.   }
  1469.   if(oldfh)        CurrentDir(oldfh);
  1470.   if(lock)        UnLock(lock);
  1471.   if(remember)        FreeRemember(&remember, TRUE);
  1472.   if(IntuitionBase)    CloseLibrary((struct Library *) IntuitionBase);
  1473.   if(rda)
  1474.   {
  1475.     FreeArgs(rda);
  1476.     FreeDosObject(DOS_RDARGS, rda);
  1477.   }
  1478.  
  1479. }
  1480.